/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
package Tools;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Ivan
 */
public class FactorySingletonCommandConsole implements IInitCommandFactory {

    private Map<String, ACommand> mapCommands;
    private Map<String, Constructor> mapConstructors;

    public FactorySingletonCommandConsole() {
        mapCommands = new HashMap<String, ACommand>(0);
        mapConstructors = new HashMap<String, Constructor>(0);
    }

    @Override
    public void initialisationMap() throws Exception {

        List<Class<?>> declaredClasses = new ArrayList<Class<?>>(0);
        Field field = null;
        String key = null;

        declaredClasses = Arrays.asList(TModel.getInstance().getClass().getDeclaredClasses());

        for (Class<?> innerClass : declaredClasses) {
            if (innerClass.getSuperclass() == ACommand.class) {

                field = innerClass.getDeclaredField("commandName");
                field.setAccessible(true);
                key = (String) field.get(null);

                Class[] constrArg = new Class[2];
                constrArg[0]  = TModel.class;
                constrArg[1]  = IExtraThreadFactory.class;
                Constructor constructor = innerClass.getDeclaredConstructor(constrArg);
                constructor.setAccessible(true);

                mapConstructors.put(key, constructor);
            }
        }
    }

    @Override
    public ACommand initializeCommand(List<String> parameters) throws Exception {
        ACommand command = null;
        String key = parameters.get(0);

        if (mapCommands.containsKey(key)) {
            command = mapCommands.get(key);
            parameters.remove(0);
            return command;
        } else {
            if (mapConstructors.containsKey(key)) {
                command = (ACommand) mapConstructors.get(key).newInstance(TModel.getInstance(),new CommandExtraThreadIOStream());
                mapCommands.put(key, command);
                parameters.remove(0);
                return command;
            } else {
                throw new IOException("command is not exist!");
            }
        }
    }
}
